package client

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"time"
)

// Client LVM Manager API 客户端
type Client struct {
	baseURL    string
	httpClient *http.Client
}

// DomainInfo Domain 信息
type DomainInfo struct {
	UUID       string   `json:"uuid"`
	Name       string   `json:"name"`
	State      string   `json:"state"`
	MaxMemory  uint64   `json:"max_memory"`
	Memory     uint64   `json:"memory"`
	CPUs       uint     `json:"cpus"`
	CPUTime    uint64   `json:"cpu_time"`
	Autostart  bool     `json:"autostart"`
	Persistent bool     `json:"persistent"`
	XMLConfig  string   `json:"xml_config,omitempty"`
	Ipv4Addrs  []string `json:"ipv4_addrs,omitempty"`
}

// CreateSpec 创建 Domain 的规格
type CreateSpec struct {
	Name        string `json:"name"`
	Memory      uint   `json:"memory"`
	VCPUs       uint   `json:"vcpus"`
	DiskPath    string `json:"disk_path"`
	DiskSize    uint   `json:"disk_size,omitempty"`
	NetworkType string `json:"network_type,omitempty"`
	NetworkName string `json:"network_name,omitempty"`
	OSType      string `json:"os_type,omitempty"`
	BootDevice  string `json:"boot_device,omitempty"`
}

// SnapshotInfo 快照信息
type SnapshotInfo struct {
	Name         string    `json:"name"`
	Domain       string    `json:"domain"`
	CreationTime time.Time `json:"creation_time"`
	State        string    `json:"state"`
	Description  string    `json:"description,omitempty"`
	Parent       string    `json:"parent,omitempty"`
	IsCurrent    bool      `json:"is_current"`
	XMLConfig    string    `json:"xml_config,omitempty"`
}

// CreateSnapshotSpec 创建快照的规格
type CreateSnapshotSpec struct {
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
	MemoryState bool   `json:"memory_state"` // 是否包含内存状态
	DiskOnly    bool   `json:"disk_only"`    // 仅磁盘快照
	Quiesce     bool   `json:"quiesce"`      // 使用 guest agent 静默文件系统
	Atomic      bool   `json:"atomic"`       // 原子操作
}

// PoolInfo 存储池信息
type PoolInfo struct {
	UUID       string `json:"uuid"`
	Name       string `json:"name"`
	State      string `json:"state"`
	Capacity   uint64 `json:"capacity"`
	Allocation uint64 `json:"allocation"`
	Available  uint64 `json:"available"`
	Autostart  bool   `json:"autostart"`
	Persistent bool   `json:"persistent"`
	Type       string `json:"type"`
	XMLConfig  string `json:"xml_config,omitempty"`
}

// VolumeInfo 存储卷信息
type VolumeInfo struct {
	Name       string `json:"name"`
	Key        string `json:"key"`
	Path       string `json:"path"`
	Type       string `json:"type"`
	Capacity   uint64 `json:"capacity"`
	Allocation uint64 `json:"allocation"`
	Pool       string `json:"pool"`
	XMLConfig  string `json:"xml_config,omitempty"`
}

// CreatePoolSpec 创建存储池规格
type CreatePoolSpec struct {
	Name string `json:"name"`
	Type string `json:"type"` // dir, disk, fs, logical, etc.
	// 特定于类型的参数
	TargetPath   string            `json:"target_path,omitempty"`   // dir, fs 类型
	SourceDevice string            `json:"source_device,omitempty"` // disk 类型
	SourceFormat string            `json:"source_format,omitempty"` // disk 类型
	ExtraOptions map[string]string `json:"extra_options,omitempty"` // 其他选项
}

// CreateVolumeSpec 创建存储卷规格
type CreateVolumeSpec struct {
	Name       string `json:"name"`
	Capacity   uint64 `json:"capacity"` // bytes
	Allocation uint64 `json:"allocation,omitempty"`
	Format     string `json:"format,omitempty"` // qcow2, raw 等
}

// NetworkInfo 网络信息
type NetworkInfo struct {
	UUID        string `json:"uuid"`
	Name        string `json:"name"`
	Active      bool   `json:"active"`
	Persistent  bool   `json:"persistent"`
	Autostart   bool   `json:"autostart"`
	Bridge      string `json:"bridge,omitempty"`
	ForwardMode string `json:"forward_mode,omitempty"`
	XMLConfig   string `json:"xml_config,omitempty"`
}

// CreateNetworkSpec 创建网络规格
type CreateNetworkSpec struct {
	Name        string `json:"name" binding:"required"`
	ForwardMode string `json:"forward_mode"` // nat, route, bridge, none
	Bridge      string `json:"bridge,omitempty"`
	IPAddress   string `json:"ip_address,omitempty"` // 例如: 192.168.100.1
	NetMask     string `json:"netmask,omitempty"`    // 例如: 255.255.255.0
	DHCPStart   string `json:"dhcp_start,omitempty"` // DHCP 起始地址
	DHCPEnd     string `json:"dhcp_end,omitempty"`   // DHCP 结束地址
}

// NewClient 创建新的客户端
func NewClient(baseURL string) *Client {
	return &Client{
		baseURL: baseURL,
		httpClient: &http.Client{
			Timeout: 30 * time.Second,
		},
	}
}

// ListDomains 列出所有 domains
func (c *Client) ListDomains(includeInactive bool) ([]DomainInfo, error) {
	params := url.Values{}
	if includeInactive {
		params.Set("inactive", "true")
	}

	var response struct {
		Domains []DomainInfo `json:"domains"`
		Count   int          `json:"count"`
	}

	if err := c.doRequest("GET", "/api/v1/domains?"+params.Encode(), nil, &response); err != nil {
		return nil, err
	}

	return response.Domains, nil
}

// GetDomain 获取单个 domain 详情
func (c *Client) GetDomain(name string, includeXML bool) (*DomainInfo, error) {
	params := url.Values{}
	if includeXML {
		params.Set("xml", "true")
	}

	var domain DomainInfo
	path := fmt.Sprintf("/api/v1/domains/%s?%s", name, params.Encode())

	if err := c.doRequest("GET", path, nil, &domain); err != nil {
		return nil, err
	}

	return &domain, nil
}

// CreateDomain 创建新的 domain
func (c *Client) CreateDomain(spec *CreateSpec) (*DomainInfo, error) {
	var domain DomainInfo
	if err := c.doRequest("POST", "/api/v1/domains", spec, &domain); err != nil {
		return nil, err
	}
	return &domain, nil
}

// CreateDomainFromXML 从 XML 创建 domain
func (c *Client) CreateDomainFromXML(xmlConfig string) (*DomainInfo, error) {
	payload := map[string]string{"xml": xmlConfig}
	var domain DomainInfo
	if err := c.doRequest("POST", "/api/v1/domains", payload, &domain); err != nil {
		return nil, err
	}
	return &domain, nil
}

// DomainAction 执行 domain 操作
func (c *Client) DomainAction(name, action string) error {
	payload := map[string]string{"action": action}
	path := fmt.Sprintf("/api/v1/domains/%s/action", name)

	var response map[string]interface{}
	return c.doRequest("POST", path, payload, &response)
}

// DeleteDomain 删除 domain 定义
func (c *Client) DeleteDomain(name string, force bool) error {
	path := fmt.Sprintf("/api/v1/domains/%s", name)
	if force {
		path += "?force=true"
	}
	var response map[string]interface{}
	return c.doRequest("DELETE", path, nil, &response)
}

// ListSnapshots 列出指定 domain 的所有快照
func (c *Client) ListSnapshots(domainName string) ([]SnapshotInfo, error) {
	var response struct {
		Snapshots []SnapshotInfo `json:"snapshots"`
		Count     int            `json:"count"`
	}

	path := fmt.Sprintf("/api/v1/snapshots?domain=%s", domainName)
	if err := c.doRequest("GET", path, nil, &response); err != nil {
		return nil, err
	}

	return response.Snapshots, nil
}

// GetSnapshot 获取单个快照详情
func (c *Client) GetSnapshot(domainName, name string) (*SnapshotInfo, error) {
	var snapshot SnapshotInfo
	path := fmt.Sprintf("/api/v1/snapshots/%s/%s", domainName, name)

	if err := c.doRequest("GET", path, nil, &snapshot); err != nil {
		return nil, err
	}

	return &snapshot, nil
}

// CreateSnapshot 创建新的快照
func (c *Client) CreateSnapshot(domainName string, spec *CreateSnapshotSpec) (*SnapshotInfo, error) {
	var snapshot SnapshotInfo
	path := fmt.Sprintf("/api/v1/snapshots/%s", domainName)

	if err := c.doRequest("POST", path, spec, &snapshot); err != nil {
		return nil, err
	}

	return &snapshot, nil
}

// RevertSnapshot 恢复到指定快照
func (c *Client) RevertSnapshot(domainName, name string) error {
	path := fmt.Sprintf("/api/v1/snapshots/%s/%s/revert", domainName, name)

	var response map[string]interface{}
	return c.doRequest("POST", path, nil, &response)
}

// DeleteSnapshot 删除快照
func (c *Client) DeleteSnapshot(domainName, name string) error {
	path := fmt.Sprintf("/api/v1/snapshots/%s/%s", domainName, name)

	var response map[string]interface{}
	return c.doRequest("DELETE", path, nil, &response)
}

// ListStoragePools 列出所有存储池
func (c *Client) ListStoragePools() ([]PoolInfo, error) {
	var response struct {
		Pools []PoolInfo `json:"pools"`
		Count int        `json:"count"`
	}

	if err := c.doRequest("GET", "/api/v1/storage/pools", nil, &response); err != nil {
		return nil, err
	}

	return response.Pools, nil
}

// GetStoragePool 获取单个存储池详情
func (c *Client) GetStoragePool(name string, includeXML bool) (*PoolInfo, error) {
	params := url.Values{}
	if includeXML {
		params.Set("xml", "true")
	}

	var pool PoolInfo
	path := fmt.Sprintf("/api/v1/storage/pools/%s?%s", name, params.Encode())

	if err := c.doRequest("GET", path, nil, &pool); err != nil {
		return nil, err
	}

	return &pool, nil
}

// CreateStoragePool 创建新的存储池
func (c *Client) CreateStoragePool(spec *CreatePoolSpec) (*PoolInfo, error) {
	var pool PoolInfo
	if err := c.doRequest("POST", "/api/v1/storage/pools", spec, &pool); err != nil {
		return nil, err
	}
	return &pool, nil
}

// StartStoragePool 启动存储池
func (c *Client) StartStoragePool(name string) error {
	path := fmt.Sprintf("/api/v1/storage/pools/%s/start", name)

	var response map[string]interface{}
	return c.doRequest("POST", path, nil, &response)
}

// StopStoragePool 停止存储池
func (c *Client) StopStoragePool(name string) error {
	path := fmt.Sprintf("/api/v1/storage/pools/%s/stop", name)

	var response map[string]interface{}
	return c.doRequest("POST", path, nil, &response)
}

// RefreshStoragePool 刷新存储池
func (c *Client) RefreshStoragePool(name string) error {
	path := fmt.Sprintf("/api/v1/storage/pools/%s/refresh", name)

	var response map[string]interface{}
	return c.doRequest("POST", path, nil, &response)
}

// DeleteStoragePool 删除存储池
func (c *Client) DeleteStoragePool(name string) error {
	path := fmt.Sprintf("/api/v1/storage/pools/%s", name)

	var response map[string]interface{}
	return c.doRequest("DELETE", path, nil, &response)
}

// ListStorageVolumes 列出存储池中的所有存储卷
func (c *Client) ListStorageVolumes(poolName string) ([]VolumeInfo, error) {
	var response struct {
		Volumes []VolumeInfo `json:"volumes"`
		Count   int          `json:"count"`
	}

	path := fmt.Sprintf("/api/v1/storage/pools/%s/volumes", poolName)
	if err := c.doRequest("GET", path, nil, &response); err != nil {
		return nil, err
	}

	return response.Volumes, nil
}

// GetStorageVolume 获取单个存储卷详情
func (c *Client) GetStorageVolume(poolName, name string, includeXML bool) (*VolumeInfo, error) {
	params := url.Values{}
	if includeXML {
		params.Set("xml", "true")
	}

	var volume VolumeInfo
	path := fmt.Sprintf("/api/v1/storage/pools/%s/volumes/%s?%s", poolName, name, params.Encode())

	if err := c.doRequest("GET", path, nil, &volume); err != nil {
		return nil, err
	}

	return &volume, nil
}

// CreateStorageVolume 在指定存储池中创建新的存储卷
func (c *Client) CreateStorageVolume(poolName string, spec *CreateVolumeSpec) (*VolumeInfo, error) {
	var volume VolumeInfo
	path := fmt.Sprintf("/api/v1/storage/pools/%s/volumes", poolName)

	if err := c.doRequest("POST", path, spec, &volume); err != nil {
		return nil, err
	}

	return &volume, nil
}

// DeleteStorageVolume 删除存储卷
func (c *Client) DeleteStorageVolume(poolName, name string) error {
	path := fmt.Sprintf("/api/v1/storage/pools/%s/volumes/%s", poolName, name)

	var response map[string]interface{}
	return c.doRequest("DELETE", path, nil, &response)
}

// ListNetworks 列出所有网络
func (c *Client) ListNetworks() ([]NetworkInfo, error) {
	var response struct {
		Networks []NetworkInfo `json:"networks"`
		Count    int           `json:"count"`
	}

	if err := c.doRequest("GET", "/api/v1/networks", nil, &response); err != nil {
		return nil, err
	}

	return response.Networks, nil
}

// GetNetwork 获取单个网络详情
func (c *Client) GetNetwork(name string, includeXML bool) (*NetworkInfo, error) {
	params := url.Values{}
	if includeXML {
		params.Set("xml", "true")
	}

	var network NetworkInfo
	path := fmt.Sprintf("/api/v1/networks/%s?%s", name, params.Encode())

	if err := c.doRequest("GET", path, nil, &network); err != nil {
		return nil, err
	}

	return &network, nil
}

// CreateNetwork 创建新的网络
func (c *Client) CreateNetwork(spec *CreateNetworkSpec) (*NetworkInfo, error) {
	var network NetworkInfo
	if err := c.doRequest("POST", "/api/v1/networks", spec, &network); err != nil {
		return nil, err
	}
	return &network, nil
}

// StartNetwork 启动网络
func (c *Client) StartNetwork(name string) error {
	path := fmt.Sprintf("/api/v1/networks/%s/start", name)

	var response map[string]interface{}
	return c.doRequest("POST", path, nil, &response)
}

// StopNetwork 停止网络
func (c *Client) StopNetwork(name string) error {
	path := fmt.Sprintf("/api/v1/networks/%s/stop", name)

	var response map[string]interface{}
	return c.doRequest("POST", path, nil, &response)
}

// DeleteNetwork 删除网络
func (c *Client) DeleteNetwork(name string) error {
	path := fmt.Sprintf("/api/v1/networks/%s", name)

	var response map[string]interface{}
	return c.doRequest("DELETE", path, nil, &response)
}

// doRequest 执行 HTTP 请求
func (c *Client) doRequest(method, path string, body, result interface{}) error {
	var reqBody io.Reader
	if body != nil {
		jsonData, err := json.Marshal(body)
		if err != nil {
			return fmt.Errorf("failed to marshal request body: %w", err)
		}
		reqBody = bytes.NewBuffer(jsonData)
	}

	req, err := http.NewRequest(method, c.baseURL+path, reqBody)
	if err != nil {
		return fmt.Errorf("failed to create request: %w", err)
	}

	if body != nil {
		req.Header.Set("Content-Type", "application/json")
	}

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("request failed: %w", err)
	}
	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("failed to read response: %w", err)
	}

	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		var errResp struct {
			Error  string `json:"error"`
			Detail string `json:"detail"`
		}
		if err := json.Unmarshal(respBody, &errResp); err == nil {
			return fmt.Errorf("API error (%d): %s - %s", resp.StatusCode, errResp.Error, errResp.Detail)
		}
		return fmt.Errorf("API error (%d): %s", resp.StatusCode, string(respBody))
	}

	if result != nil {
		if err := json.Unmarshal(respBody, result); err != nil {
			return fmt.Errorf("failed to unmarshal response: %w", err)
		}
	}

	return nil
}
